package com.vhly.appspot.twitter;

import com.google.appengine.api.memcache.stdimpl.GCacheFactory;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.api.users.UserService;
import com.vhly.appspot.ResponseData;
import com.vhly.appspot.util.StreamUtil;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.cache.Cache;
import javax.cache.CacheFactory;
import javax.cache.CacheManager;
import javax.cache.CacheException;
import java.io.IOException;
import java.util.logging.Logger;
import java.util.Collections;
import java.util.Map;
import java.util.HashMap;

/**
 * Created by IntelliJ IDEA.
 * User: vhly
 * Date: 2009-11-3
 * Time: 10:39:46
 *
 * @author vhly[FR]
 */
public final class TwitterServlet extends HttpServlet {

    private static Logger log = Logger.getLogger("TwitterServlet");

    private static Cache twCache;

    @Override
    public void init() throws ServletException {
        super.init();
        if (twCache == null) {
            try {
                CacheManager manager = CacheManager.getInstance();
                CacheFactory cacheFactory = manager.getCacheFactory();
                Map<Object, Object> map = new HashMap<Object, Object>();
                twCache = cacheFactory.createCache(map);
                map = null;
                cacheFactory = null;
                manager = null;
                log.info("Create Cache");
            } catch (CacheException ce) {

            }
        }
    }

    @Override
    public void destroy() {
        super.destroy();
        twCache.clear();
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        work(request, response);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        work(request, response);
    }

    private void work(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        log.info("process");
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        String md = request.getMethod();
        if (md.equals("GET")) {
            String au = request.getParameter("auth");
            if (au != null) {
                // TODO Twitter 's OAuth Callback
            } else {
                String action = request.getParameter("action");
                if (action != null && action.length() > 0) {
                    if (action.equals("rc")) {
                        // clear cache
                        clearCache(request, response);
                    }
                } else {
                    response.setStatus(HttpServletResponse.SC_OK);
                    outputTextContent(response, "text/html", "<html><head><title>TW Info<title></head><body>TW - Twitter API Proxy by vhly[FR]<br/>Version: " + Version.ver + "</body></html>");
                }
            }
        } else if (md.equals("POST")) {
            long ct = System.currentTimeMillis();
            ServletInputStream in = request.getInputStream();

            // TODO 获取请求数据
            byte[] data = StreamUtil.readStream(in);
            boolean dataOK = data != null && data.length > 0;
            RequestData rd = new RequestData();
            if (dataOK) {
                dataOK = rd.read(data);
            }
            long ct2;
            if (dataOK) {
                // TODO 获取缓存，目前只支持 GET方式
                ResponseData responseData = null;
                boolean hasCache = false;
                if (rd.httpmethod == Constants.HTTP_API_GET && rd.authType == Constants.AUTH_TYPE_NONE) {
                    if (twCache.containsKey(rd.getIdentifier())) {
                        hasCache = true;
                    }
                }
                if (hasCache) {
                    responseData = new ResponseData();
                    responseData.data = (byte[]) twCache.get(rd.getIdentifier());
                    responseData.stateCode = 200;
                    responseData.contentLength = responseData.data.length;
                } else {
                    responseData = TwitterClient.processRequest(rd);
                    if (responseData.stateCode == HttpServletResponse.SC_OK) {
//                        log.info("Response OK");
                        if (rd.httpmethod == Constants.HTTP_API_GET && rd.authType == Constants.AUTH_TYPE_NONE) {
                            twCache.put(rd.getIdentifier(), responseData.data);
                            log.info("Save Cache");
                        }
                    } else {
                        log.warning("Resp Error" + responseData.stateCode);
                    }
                }

                response.setStatus(responseData.stateCode);
                byte[] buf = responseData.data;
                response.setContentLength(responseData.contentLength);
                // TODO GAE(Google App Engine) use Request's User-Agent, Accept-Encoding, and Response's Content-Type to compress
                response.setContentType("text/html");
                if (buf != null && buf.length > 0) {
                    ServletOutputStream out = response.getOutputStream();
                    out.write(buf);
                    out.close();
//                    String xml = new String(buf);
//                    log.info(xml);
                }
                ct2 = System.currentTimeMillis();
                log.info("post process time: " + (ct2 - ct));
                rd.dealloc();
                responseData.dealloc();
            } else {
                // TODO error format for request data
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            }
        }
    }

    private void outputTextContent(HttpServletResponse response, String contentType, String content) throws IOException {
        response.setContentType(contentType);
        ServletOutputStream out = response.getOutputStream();
        out.print(content);
        StreamUtil.close(out);
    }

    private void clearCache(HttpServletRequest request, HttpServletResponse response) throws IOException {
        UserService service = UserServiceFactory.getUserService();
        User user = service.getCurrentUser();
        if (user != null) {
            String account = user.getEmail();
            if (account.equals("avfinder@gmail.com")) {
                if (twCache != null) {
                    twCache.clear();
                }
                outputTextContent(response, "text/html", "<html><body>Clear Cache OK!</body></html>");
            } else {
                outputTextContent(response, "text/html", "<html><body>Must Admin can Clear Cache!</body></html>");
            }
        } else {
            String loc = service.createLoginURL(request.getRequestURI());
            response.sendRedirect(loc);
        }
    }
}
